package com.ruoyi.weiriya.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.weiriya.domain.dto.StatisticalReportDto;
import com.ruoyi.weiriya.domain.dto.StatisticalReportOrderDto;
import com.ruoyi.weiriya.domain.dto.StatisticalReportRecordDto;
import com.ruoyi.weiriya.domain.vo.StatisticalReportVo;
import com.ruoyi.weiriya.mapper.WStatisticalReportMapper;
import com.ruoyi.weiriya.service.IWStatisticalReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Period;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台公告Service业务层处理
 * 
 * @author lynn
 * @date 2023-08-01
 */
@Service
public class WStatisticalReportServiceImpl  implements IWStatisticalReportService
{
    @Autowired
    private WStatisticalReportMapper statisticalReportMapper;

    @Override
    public List<StatisticalReportVo> statisticalMemberNum(String type) {
        if("vehicleType".equals(type)){
            return statisticalReportMapper.statisticalMemberNumByVehicleType();
        }else{
            return statisticalReportMapper.statisticalMemberNumByArea();
        }
    }

    @Override
    public List<StatisticalReportVo> statisticalIncome(StatisticalReportDto dto) {
        String type = dto.getType();

        if("1".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);
            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalIncome(startTime, endTime, "%Y");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else if("2".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalIncome(startTime, endTime, "%Y-%m");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else {

            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalIncome(startTime, endTime, "%Y-%m-%d");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);
        }
    }

    @Override
    public List<StatisticalReportVo> statisticalOrder(StatisticalReportOrderDto dto) {

        String type = dto.getType();
        String orderType = dto.getOrderType();
        if("1".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);
            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalOrder(startTime, endTime, "%Y", orderType);
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else if("2".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalOrder(startTime, endTime, "%Y-%m", orderType);
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else {

            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalOrder(startTime, endTime, "%Y-%m-%d", orderType);
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);
        }
    }

    @Override
    public Map<String, Object> statisticalRecord(StatisticalReportRecordDto dto) {
        String type = dto.getType();
        String recordType = dto.getRecordType();
        if(StringUtils.isBlank(recordType)){
            String format;
            if("1".equals(type)){
                format = "%Y";
            } else if("2".equals(type)){
                format = "%Y-%m";
            } else {
                format = "%Y-%m-%d";
            }

            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos1 = getStatisticalReportVos(format, "1", startTime, endTime);
            List<StatisticalReportVo> statisticalReportVos2 = getStatisticalReportVos(format, "2", startTime, endTime);
            List<StatisticalReportVo> statisticalReportVos3 = getStatisticalReportVos(format, "3", startTime, endTime);
            List<StatisticalReportVo> statisticalReportVos4 = getStatisticalReportVos(format, "4", startTime, endTime);
            List<StatisticalReportVo> statisticalReportVos5 = getStatisticalReportVos(format, "5", startTime, endTime);
            List<StatisticalReportVo> statisticalReportVos6 = getStatisticalReportVos(format, "6", startTime, endTime);
            List<StatisticalReportVo> vos1 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos1);
            List<StatisticalReportVo> vos2 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos2);
            List<StatisticalReportVo> vos3 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos3);
            List<StatisticalReportVo> vos4 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos4);
            List<StatisticalReportVo> vos5 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos5);
            List<StatisticalReportVo> vos6 = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos6);
            Map<String, Object> map = new HashMap<>();
            map.put("keys", vos1.stream().map(StatisticalReportVo::getKey).collect(Collectors.toList()));
            map.put("vipCharge", vos1.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));
            map.put("vipDeposit", vos2.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));
            map.put("tempCharge", vos3.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));
            map.put("tempDeposit", vos4.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));
            map.put("allCharge", vos5.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));
            map.put("allDeposit", vos6.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList()));

            return map;

        }
        String format;
        if("1".equals(type)){
            format = "%Y";
        } else if("2".equals(type)){
            format = "%Y-%m";
        } else {
            format = "%Y-%m-%d";
        }
        String startTime = getStartTime(dto);
        String endTime = getEndTime(dto);

        List<StatisticalReportVo> statisticalReportVos = getStatisticalReportVos(format, recordType, startTime, endTime);
        List<StatisticalReportVo> vos = getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);
        List<String> keys = vos.stream().map(StatisticalReportVo::getKey).collect(Collectors.toList());
        List<String> values = vos.stream().map(StatisticalReportVo::getValue).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("keys", keys);
        map.put("values", values);
        return map;
    }


    @Override
    public List<StatisticalReportVo> statisticalConsume(StatisticalReportDto dto) {

        String type = dto.getType();

        if("1".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);
            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalConsume(startTime, endTime, "%Y");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else if("2".equals(type)){
            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalConsume(startTime, endTime, "%Y-%m");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);

        } else {

            String startTime = getStartTime(dto);
            String endTime = getEndTime(dto);

            List<StatisticalReportVo> statisticalReportVos = statisticalReportMapper.statisticalConsume(startTime, endTime, "%Y-%m-%d");
            return getStatisticalReportVos(type, startTime, endTime, statisticalReportVos);
        }
    }

    private List<StatisticalReportVo> getStatisticalReportVos(String format, String recordType, String startTime, String endTime) {
        List<StatisticalReportVo> statisticalReportVos = new ArrayList<>();
        if(recordType.equals("1")) {
            statisticalReportVos = statisticalReportMapper.statisticalChargeRecord(startTime, endTime, format, "1");
        } else if(recordType.equals("2")){
            statisticalReportVos = statisticalReportMapper.statisticalDepositRecord(startTime, endTime, format, "1");
        } else if(recordType.equals("3")){
            statisticalReportVos = statisticalReportMapper.statisticalChargeRecord(startTime, endTime, format, "2");
        } else if(recordType.equals("4")){
            statisticalReportVos = statisticalReportMapper.statisticalDepositRecord(startTime, endTime, format, "2");
        } else if(recordType.equals("5")){
            statisticalReportVos = statisticalReportMapper.statisticalChargeRecord(startTime, endTime, format, null);
        } else if(recordType.equals("6")){
            statisticalReportVos = statisticalReportMapper.statisticalDepositRecord(startTime, endTime, format, null);
        }
        return statisticalReportVos;
    }

    private String getStartTime(StatisticalReportDto dto){
        String type = dto.getType();
        String startTime = dto.getStartTime();
        Date now = new Date();
        if("1".equals(type)){
            if(StringUtils.isBlank(startTime)){
                Date date = DateUtils.addYears(now, -4);
                DateTime dateTime = DateUtil.beginOfYear(date);
                startTime = dateTime.toString();
            } else {
                startTime += "-01-01 00:00:01";
            }
        } else if("2".equals(type)){

            if(StringUtils.isBlank(startTime)){
                DateTime dateTime = DateUtil.beginOfYear(now);
                startTime = dateTime.toString();
            } else {
                startTime += "-01 00:00:01";
            }
        } else {
            if(StringUtils.isBlank(startTime)){
                DateTime dateTime = DateUtil.beginOfMonth(now);
                startTime = dateTime.toString();
            } else {
                startTime += " 00:00:01";
            }
        }
        return startTime;
    }

    private String getEndTime(StatisticalReportDto dto){
        String type = dto.getType();
        String endTime = dto.getEndTime();
        Date now = new Date();
        if("1".equals(type)){
            if(StringUtils.isBlank(endTime)){
                endTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", now);
            } else {
                endTime += "-01-01";
                DateTime dateTime = DateUtil.endOfYear(DateUtils.dateTime(DateUtils.YYYY_MM_DD, endTime));
                endTime = dateTime.toString();
            }

        } else if("2".equals(type)){
            if(StringUtils.isBlank(endTime)){
                DateTime dateTime = DateUtil.endOfYear(now);
                endTime = dateTime.toString();
            } else {
                endTime += "-01";
                DateTime dateTime = DateUtil.endOfMonth(DateUtils.dateTime(DateUtils.YYYY_MM_DD, endTime));
                endTime = dateTime.toString();
            }
        } else {
            if(StringUtils.isBlank(endTime)){
                DateTime dateTime = DateUtil.endOfMonth(now);
                endTime = dateTime.toString();
            } else {
                endTime += " 23:59:59";
            }
        }
        return endTime;
    }


    private List<StatisticalReportVo> getStatisticalReportVos(String type, String startTime, String endTime, List<StatisticalReportVo> statisticalReportVos) {
        Map<String, String> voMap = statisticalReportVos.stream().collect(Collectors.toMap(StatisticalReportVo::getKey, StatisticalReportVo::getValue));

        Date start = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", startTime);
        Date end = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", endTime);

        List<StatisticalReportVo> vos = new ArrayList<>();
        if("1".equals(type)) {
            int startYear = DateUtil.year(start);
            int endYear = DateUtil.year(end);
            for (int i = startYear; i <= endYear; i++) {
                StatisticalReportVo vo = new StatisticalReportVo();
                vo.setKey(i + "");
                vo.setValue(StringUtils.isBlank(voMap.get(i + "")) ? "0" : voMap.get(i + ""));
                vos.add(vo);
            }
        }else if("2".equals(type)) {
            int monthDiff = getMonthDiff(start, end);
            for (int i = 0; i <= monthDiff; i++) {
                Date date = DateUtils.addMonths(start, i);
                StatisticalReportVo vo = new StatisticalReportVo();
                String key = DateUtils.parseDateToStr("yyyy-MM", date);
                vo.setKey(key);
                vo.setValue(StringUtils.isBlank(voMap.get(key)) ? "0" : voMap.get(key));
                vos.add(vo);
            }
        } else {
            long between = DateUtil.between(start, end, DateUnit.DAY);
            for (int i = 0; i <= between; i++) {
                Date date = DateUtils.addDays(start, i);
                StatisticalReportVo vo = new StatisticalReportVo();
                String key = DateUtils.parseDateToStr("yyyy-MM-dd", date);
                vo.setKey(key);
                vo.setValue(StringUtils.isBlank(voMap.get(key)) ? "0" : voMap.get(key));
                vos.add(vo);
            }
        }
        return vos;
    }

    public static int getMonthDiff(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);

        int yearDiff = (cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR)) * 12;
        int monthDiff = cal1.get(Calendar.MONTH) - cal2.get(Calendar.MONTH);

        return Math.abs(yearDiff + monthDiff);
    }

}
